
#include <gtk/gtk.h>
#include <stdio.h>
#include "support.h"
#include "ioview.h"
#include "window.h"
#include "config.h"
#include "statusbar.h"
#include "toolbar_second.h"
#include "memview.h"
#include "widget.h"

/*################ static functions #####################*/
static GtkWidget *gsim_get_ioview(void);
static void reset_ioview(void);
static void ioview_goto_port(GtkWidget *which,gpointer data);

/*################ globals ####################*/
static GtkWidget *ioview_tree;
GtkTreeModel *ioview_model;
GtkTreeIter ioview_iter;
GtkTreeSelection *ioview_selector;

/*###################### Show / hide Ioview ######################*/
void show_hide_ioview(void)
{
	if(state_ioview)
	{
		state_ioview=0;
		gtk_widget_hide_all(gsim_ioview_box);
		gsim_update_statusbar(DESC_SBAR,_("Ioview off"));
	}
	else
	{
		state_ioview=1;
		gtk_widget_show_all(gsim_ioview_box);
		gsim_update_statusbar(DESC_SBAR,_("Ioview on"));
	}
	return;
}

/*################ reset the ioview ######################*/
static void reset_ioview(void)
{
	g_object_ref(G_OBJECT(ioview_model));
	gtk_tree_view_set_model(GTK_TREE_VIEW(ioview_tree),NULL);
	
	gint i;
	gchar addr[5];
	addr[4]='\0';
	GtkTreeIter ioview_iter;
	gtk_tree_model_get_iter_first(ioview_model,&ioview_iter);
	for(i=0x00;i<=0xff;i++)
	{
		sprintf(addr,"%02X",i);
		gtk_list_store_set(GTK_LIST_STORE(ioview_model),
									&ioview_iter,MEM_ADDR_COL,addr,MEM_DATA_COL,"00",-1);
		gtk_tree_model_iter_next(ioview_model,&ioview_iter);
	}
	
	gtk_tree_view_set_model(GTK_TREE_VIEW(ioview_tree),ioview_model);
	g_object_unref(G_OBJECT(ioview_model));
	return;
}

/*#################### Scroll to the cell ########################*/
void ioview_scroll_to_port(const gchar *where)
{
	GtkTreePath *path;
	gchar p_str[4];
	gint x;
	
	sscanf(where,"%X",&x);
	sprintf(p_str,"%d",x);
	
	/*scroll to cell and place tracker there*/
	path=gtk_tree_path_new_from_string(p_str);
	gtk_tree_model_get_iter(ioview_model,&ioview_iter,path);
	gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ioview_tree),path,NULL,FALSE,0,0);
	
	gtk_list_store_set(GTK_LIST_STORE(ioview_model),
									&ioview_iter,MEM_TR_COL,NULL,-1);
	gtk_list_store_set(GTK_LIST_STORE(ioview_model),
									&ioview_iter,MEM_TR_COL,data_tracker_pixmap,-1);
	gtk_tree_selection_select_path(ioview_selector,path);
	
	return;
}
	

/*#################### Go to the port in the find entry ###################*/
static void ioview_goto_port(GtkWidget *which,gpointer data)
{
	const gchar *goto_path;
	goto_path=gtk_entry_get_text(GTK_ENTRY(data));
	if(g_ascii_strcasecmp(goto_path,""))
		ioview_scroll_to_port(goto_path);
	return;
}

/*################ Make the port view box ####################*/
GtkWidget *gsim_get_ioview_box( void )
{
	GtkWidget *ioview_table;
	ioview_table=gtk_table_new( 6,3,FALSE);
	
	/*ioview label*/
	GtkWidget *ioview_label;
	ioview_label=gtk_label_new("PORT");
	gtk_table_attach(GTK_TABLE(ioview_table),ioview_label,0,2,0,1,0,0,5,0);
	
	/*pack close button*/
	GtkWidget *ioview_close;
	ioview_close=gsim_small_close_button_new(-1,-1);;
	gtk_table_attach( GTK_TABLE( ioview_table ), ioview_close, 2 , 3 , 0 , 1 , 0 , 0, 0 , 0 );
	gtk_tooltips_set_tip( gsim_tooltips, ioview_close, _("Close Port View"),NULL);
	g_signal_connect(ioview_close,"clicked",G_CALLBACK(show_hide_ioview),NULL);
	
	/*pack the seperater*/
	GtkWidget *sep1;
	sep1=gtk_hseparator_new( );
	gtk_table_attach( GTK_TABLE( ioview_table ), sep1, 0 , 3 , 1 , 2 , GTK_FILL|GTK_EXPAND , 0, 0 , 2 );
	
	/*pack the reset button*/
	GtkWidget *ioview_reset;//,*reset_label;
	ioview_reset=gsim_small_reset_button_new(-1,-1);
	/*reset_label=gtk_label_new("<span size=\"small\" >R</span>");
	gtk_label_set_use_markup(GTK_LABEL(reset_label),TRUE);
	gtk_container_add(GTK_CONTAINER(ioview_reset),reset_label);
	gtk_button_set_relief(GTK_BUTTON(ioview_reset), GTK_RELIEF_HALF);
	gtk_widget_set_size_request( ioview_reset , 20, 20 );
	gtk_button_set_alignment(GTK_BUTTON(ioview_reset),0.0,0.0);*/
	gtk_table_attach( GTK_TABLE( ioview_table ), ioview_reset, 0 , 1 , 2 , 3 , 0 , 0, 0 , 0 );
	gtk_tooltips_set_tip( gsim_tooltips, ioview_reset,_("Reset the ports"),NULL);
	g_signal_connect(ioview_reset,"clicked",G_CALLBACK(reset_ioview),NULL);
	
	/*pack two unsused buttons*/
	GtkWidget *io_1;
	io_1=gsim_empty_button_new(-1,-1);
	//gtk_button_set_relief(GTK_BUTTON(io_1), GTK_RELIEF_HALF);
	//gtk_widget_set_size_request( io_1 , 22, 22 );
	gtk_table_attach( GTK_TABLE( ioview_table ), io_1, 1 , 2 , 2 , 3 , 0 , 0, 0 , 0 );
	
	GtkWidget *io_2;
	io_2=gsim_empty_button_new(-1,-1);
	//gtk_button_set_relief(GTK_BUTTON(io_2), GTK_RELIEF_HALF);
	//gtk_widget_set_size_request( io_2 , 22, 22 );
	gtk_table_attach( GTK_TABLE( ioview_table ), io_2, 2 , 3 , 2 , 3 , 0 , 0, 0 , 0 );
	
	/*pack the ioory location find entry and button*/
	GtkWidget *iofind_box,*iofind_entry,*iofind_button;
	iofind_box=gtk_hbox_new(FALSE,0);
	iofind_entry=gtk_entry_new_with_max_length(2);
	gtk_widget_set_size_request( iofind_entry ,40,-1);
	gtk_entry_set_text(GTK_ENTRY(iofind_entry),gsim_values.iofind);
	iofind_button=gsim_find_button_new(-1,-1);
	/*gtk_widget_set_size_request( iofind_button ,25,-1);
	gtk_button_set_relief(GTK_BUTTON(iofind_button), GTK_RELIEF_NONE);*/
	gtk_box_pack_start(GTK_BOX(iofind_box),iofind_entry,0,0,0);
	gtk_box_pack_start(GTK_BOX(iofind_box),iofind_button,0,0,0);
	gtk_table_attach( GTK_TABLE( ioview_table ), iofind_box, 0 , 3 , 3 , 4 , 0 , 0, 0 , 0 );
	gtk_tooltips_set_tip( gsim_tooltips, iofind_entry, _("Enter a port to find"),NULL);
	gtk_tooltips_set_tip( gsim_tooltips, iofind_button,_("Find the port"),NULL);
	g_signal_connect(iofind_entry,"changed",G_CALLBACK(on_address_changed),NULL);
	g_signal_connect(iofind_entry,"activate",G_CALLBACK(ioview_goto_port),iofind_entry);
	g_signal_connect(iofind_button,"clicked",G_CALLBACK(ioview_goto_port),iofind_entry);
	
	/*pack the scorrlled window containing gsim_io_tree*/
	
	GtkWidget *ioview_scroll;
	ioview_scroll=gtk_scrolled_window_new(NULL,NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ioview_scroll),GTK_POLICY_NEVER,GTK_POLICY_AUTOMATIC);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ioview_scroll),GTK_SHADOW_IN);
	gtk_table_attach( GTK_TABLE( ioview_table ), ioview_scroll, 0 , 3 , 4 , 6 , 
											GTK_FILL|GTK_SHRINK , GTK_FILL|GTK_EXPAND, 0 , 0 );
	gtk_container_add(GTK_CONTAINER(ioview_scroll),gsim_get_ioview());
	
	/*pack in frame and return*/
	GtkWidget *ioview_frame;
	ioview_frame=gtk_frame_new(NULL);
	gtk_container_add(GTK_CONTAINER(ioview_frame),ioview_table);
	
	return ioview_frame;
}


/*########################### Ioview Tree ############################*/
static GtkWidget *gsim_get_ioview(void)
{
	GtkListStore *ioview_store;
	
	ioview_store=gtk_list_store_new(3,G_TYPE_STRING,G_TYPE_STRING,GDK_TYPE_PIXBUF);
	ioview_tree=gtk_tree_view_new_with_model(GTK_TREE_MODEL(ioview_store));
	ioview_model=gtk_tree_view_get_model(GTK_TREE_VIEW(ioview_tree));
	ioview_selector=gtk_tree_view_get_selection(GTK_TREE_VIEW(ioview_tree));
	g_object_unref(G_OBJECT(ioview_store));
	
	/*------------make the columns and cells--------------------*/
	GtkTreeViewColumn *ioview_column;
	GtkCellRenderer *ioview_address,*ioview_data,*ioview_tracker;
	
	ioview_address=gtk_cell_renderer_text_new();
	g_object_set(G_OBJECT(ioview_address),"cell-background",gsim_colors.ioview_addr_bg,"height",20,NULL);
	ioview_column=gtk_tree_view_column_new_with_attributes("P#",ioview_address,"text",IO_ADDR_COL,NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(ioview_tree),ioview_column);
	 gtk_tree_view_column_set_spacing(ioview_column,0);

	ioview_data=gtk_cell_renderer_text_new();
	g_object_set(G_OBJECT(ioview_data),//"background",gsim_colors.ioview_data_bg,
	                  "foreground",gsim_colors.ioview_data_fg,"editable",TRUE,NULL);
	ioview_column=gtk_tree_view_column_new_with_attributes("D#",ioview_data,"text",IO_DATA_COL,NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(ioview_tree),ioview_column);
	g_signal_connect(ioview_data,"edited",G_CALLBACK(view_data_edited),ioview_model);
	gtk_tree_view_column_set_spacing(ioview_column,0);
	
	ioview_tracker=gtk_cell_renderer_pixbuf_new();
	g_object_set(G_OBJECT(ioview_tracker),"cell-background","gray66",NULL);
	gtk_tree_view_column_pack_end(ioview_column,ioview_tracker,TRUE);
	gtk_tree_view_column_set_attributes(ioview_column,ioview_tracker,"pixbuf",IO_TR_COL,NULL);
	gtk_tree_view_column_set_spacing(ioview_column,0);
	
	gtk_tooltips_set_tip(gsim_tooltips,ioview_tree,"PORT : DATA",NULL);
	
	/*initilise the data in the ioview*/
	/*first detach model and again attack later due to speed issues*/
	g_object_ref(G_OBJECT(ioview_model));
	gtk_tree_view_set_model(GTK_TREE_VIEW(ioview_tree),NULL);
	
	gint i;
	gchar port[3];
	port[2]='\0';
	gchar data[3];
	data[2]='\0';
	for(i=0;i<256;i++)
	{
		sprintf(port,"%02X",i);
		sprintf(data,"%02X",*(gsim_values.port_data+i));
		gtk_list_store_append(GTK_LIST_STORE(ioview_model),&ioview_iter);
		gtk_list_store_set(GTK_LIST_STORE(ioview_model),
									&ioview_iter,IO_ADDR_COL,port,IO_DATA_COL,data,-1);
	}
	
	/*pack pixmap in third col*/
	gtk_tree_model_get_iter_first(ioview_model,&ioview_iter);
	gtk_list_store_set(GTK_LIST_STORE(ioview_model),
									&ioview_iter,MEM_TR_COL,data_tracker_pixmap,-1);
	
	gtk_tree_view_set_model(GTK_TREE_VIEW(ioview_tree),ioview_model);
	g_object_unref(G_OBJECT(ioview_model));

	return ioview_tree;
}
